import { MapleStoryMap } from "../map/map.js";
import share from "../share.js";
import { Player } from "../char/player.js";
import { Mobs } from "../char/mobs.js";
import sceneContainer from './container.js';
import { AudioComponent } from "../audio.js";
import { Keyboard } from "../io/keyboard.js";
export class MapScene {
  constructor(resource, app, stage, backStage, MapConfig) {
    this.mapId = MapConfig.map.mapId;
    this.mapSort = MapConfig.map.mapSort;
    this.playerInfo = MapConfig.player.Info;

    this.scaleX = app.view.width / 800;
    this.scaleY = this.scaleX;

    // test ---------------
    stage.scale.set(this.scaleX);
    // test ----------------
    this.resource = resource;
    this.app = app;
    this.stage = stage;
    this.backStage = backStage;

    this.mapInfo = {};
    this.loading = false;
    this.mobs = new Mobs();

    // io
    this.keyboard = new Keyboard;

    // 向场景容器中添加
    sceneContainer.mobs = this.mobs;

    this.mapleStoryMap = new MapleStoryMap(resource, stage, backStage);

    this.player = new Player(resource, stage, this.keyboard);

    // 刚进图时，让镜头瞬间到玩家附近。
    // 随后延迟跟进。
    this.initStateX = false;
    this.initStateY = false;

    // 屏幕是否固定, 如果地图比屏幕小。就固定在stage = -VRLeft or
    this.staticX = false;
    this.staticY = false;

    // bgm
    this.bgm = null;
  }

  /**
   * @public
   * @param {string} - 如果是通过传送门传送，会传入目标地图，传送门位置字符串，遍历下一张地图传送门集合，查找到与该字符串匹配的传送门
   */
  async switchMap(mapSort, mapId, portalTn) {
    this.loading = true;
    this.initStateX = false;
    this.initStateY = false;
    // map资源从stage中移除
    this.mapleStoryMap.destroy();
    this.mobs.destroy();
    // 停止player更新
    this.player.stop();
    this.mapSort = mapSort;
    this.mapId = mapId;
    // await this.resource.load(
    //   `Map/Map/${mapSort}`,
    //   `./Map/Map/${mapSort}/${mapId}.json`
    // );
    await this.mapleStoryMap.load(mapSort, mapId);
    // 如果是通过传送门
    if (portalTn) {
      let playerX = 0;
      let playerY = 0;
      // 切换后，已经把下张地图的信息加载到resource中。
      const NextMap = this.resource.Content.Map.Map[this.mapSort][this.mapId];

      for (let portal of Object.values(NextMap.portal)) {
        portal.x = Number(portal.x);
        portal.y = Number(portal.y);
        if (portal.pn === portalTn) {
          playerX = portal.x;
          playerY = portal.y;
          break;
        }
      }
      this.player.position.x = playerX;
      this.player.position.y = playerY - 5;
      this.player.phobj.set_x(playerX)
      this.player.phobj.set_y(playerY - 5)
    }

    this.mapInfo = this.resource.Content.Map.Map[this.mapSort][this.mapId].info;
    sceneContainer.footholdtree = this.mapleStoryMap.footholdtree;
    sceneContainer.ladderRopes = this.mapleStoryMap.ladderRopes;
    this.player.switchPhysics(sceneContainer.footholdtree)
    await this.initBgm();
    // await this.initMobs();
    this.loading = false;
    this.draw();
    this.player.play();
  }

  async initMobs() {
    const life = this.resource.Content.Map.Map[this.mapSort][this.mapId].life;
    this.mobs.init(this.resource);
    await this.mobs.merge(life);
  }

  async initBgm() {
    this.bgm && this.bgm.stop();
    const bgmPath = this.mapInfo.bgm.split('/');
    const root = bgmPath[0],
      name = bgmPath[1];
    const value = this.resource.Content.Sound[`${root}.img`][name];

    // this.bgm = new AudioComponent({ loop: true });
    // await this.bgm.bind(name, value)
    // this.bgm.start(name)
  }

  async initPlayer() {
    await this.player.init(this.playerInfo);
  }
  /**
   * @public
   */
  async init() {
    const stage = this.stage;

    const backStage = this.backStage;
    const resource = this.resource;

    this.keyboard.init();

    await share.init(resource, stage);
    await this.initPlayer();
    await this.switchMap(this.mapSort, this.mapId);
    this.player.onTransfer = async () => {
      const Map = this.resource.Content.Map.Map[this.mapSort][this.mapId];
      const { x, y } = this.player.position;
      let tm = "";
      let tn = "";
      for (let portal of Object.values(Map.portal)) {
        portal.x = Number(portal.x);
        portal.y = Number(portal.y);
        if (x >= portal.x - 20 && x <= portal.x + 20) {
          if (y >= portal.y - 40 && y <= portal.y + 10) {
            tm = portal.tm;
            tn = portal.tn;
            break;
          }
        }
      }
      // 没有站在传送点上
      if (tm.length === 0 && tn.length === 0) {
        return;
      }
      // 这tmd跑哪去了？
      if (tm === 999999999) {
        return;
      }
      await this.switchMap(this.mapSort, ('' + tm).padStart(9, 0) + ".img", tn);
    };
  }
  draw() {
    this.mapleStoryMap.draw();
    // this.mobs.draw(this.stage);
    const { VRBottom, VRTop, VRLeft, VRRight } = this.mapInfo;
    console.log(VRBottom)
    if (VRRight - VRLeft <= this.app.view.width) {
      this.staticX = true;
    } else {
      this.staticX = false;
    }
    if (VRBottom - VRTop <= this.app.view.height) {
      this.staticY = true;
    } else {
      this.staticY = false;
    }
  }

  autoStagePosition() {
    const player = this.player;
    const stage = this.stage;
    const app = this.app;
    let { VRBottom, VRTop, VRLeft, VRRight } = this.mapInfo;
    VRLeft *= this.scaleX;
    VRRight *= this.scaleX;
    VRBottom *= this.scaleY;
    VRTop *= this.scaleY;
    const viewWidth = app.view.width;
    const viewHeight = app.view.height;
    const sy =
      -Math.round(player.position.y * this.scaleY) + viewHeight / 1.6;
    const sx = -(player.position.x * this.scaleX) + viewWidth / 2;
    let stickYSpeed = 4;
    let stickXSpeed = player.xSpeed * 4;
    if (!this.staticX) {
      if (!this.initStateX) {
        stage.x = sx;
        this.initStateX = true;
      }
      // if (stage.x <= sx - stickXSpeed * 2) {
      //   if (stage.x <= sx - stickXSpeed * 36) {
      //     stage.x += stickXSpeed;
      //   } else {
      //     stage.x += stickXSpeed >> 2;
      //   }
      // }
      // if (stage.x >= sx + stickXSpeed * 2) {
      //   if (stage.x >= sx + stickXSpeed * 36) {
      //     stage.x -= stickXSpeed;
      //   } else {
      //     stage.x -= stickXSpeed >> 2;
      //   }
      // }
      stage.x = sx;
      if (stage.x >= -Number(VRLeft)) {
        stage.x = -Number(VRLeft);
      } else if (stage.x <= -Number(VRRight) + viewWidth) {
        stage.x = -Number(VRRight) + viewWidth;
      }
    } else {
      stage.x = -VRLeft;
    }

    if (!this.staticY) {
      if (!this.initStateY) {
        stage.y = sy;
        this.initStateY = true;
      }
      stage.y = sy;
      // if (stage.y <= sy) {
      //   if (stage.y <= -Math.round(player.position.y) + app.view.height) {
      //     stage.y += 2 * stickYSpeed;
      //   } else {
      //     stage.y += stickYSpeed;
      //   }
      //   if (stage.y >= sy) {
      //     stage.y = sy;
      //   }
      // }
      // if (stage.y >= sy) {
      //   if (stage.y >= -Math.round(player.position.y) + app.view.height) {
      //     // stage.y -= Math.abs(player.ySpeed);
      //     stage.y -= 2 * stickYSpeed;
      //   } else {
      //     stage.y -= stickYSpeed;
      //   }
      //   if (stage.y <= sy) {
      //     stage.y = sy;
      //   }
      // }
      if (stage.y >= -Number(VRTop)) {
        stage.y = -Number(VRTop);
      } else if (stage.y <= -(Number(VRBottom) - viewHeight)) {
        stage.y = -(Number(VRBottom) - viewHeight);
      }
    } else {
      stage.y = -VRTop;
    }
  }

  update() {
    if (this.loading) {
      console.log("loading");
      return;
    }
    const stage = this.stage;
    var then = Date.now();
    var count = 0;

    count++;
    if (count % 20 === 0) {
      var time = (Date.now() - then) / count;
      var ms = Math.round(time * 1000) / 1000;
      var fps = Math.round(100000 / ms) / 100;
      // console.log(`count: ${count}\t${ms}ms/frame\t${fps}fps`)
    }
    // this.mobs.update();
    // 注意！下面两句不能换位置。
    this.autoStagePosition();
    this.player.update(stage, Number(this.mapInfo.VRLeft), Number(this.mapInfo.VRRight));
    this.mapleStoryMap.update()
  }

  destroy() {
    this.mobs.destroy();
    this.keyboard.destroy();
    this.mapleStoryMap.destroy();
    this.player.destroy();
    this.bgm.stop();
  }
}
